package edge.display.backend.Entity;

import edge.display.backend.Entity.ECharts.AvgData;
import edge.display.backend.Entity.ECharts.DynamicData;
import edge.display.backend.Entity.ECharts.StatData;
import edge.display.backend.KEY_STORE;
import edge.display.backend.Utils.StatUtils;
import lombok.Data;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 任务统计实体类
 *
 * @author Amane Hayaashi
 * @date 2020/11/8
 * @since 1.0
 */

@Data
public class TaskStat {

    private Task task;

    private List<Object> taskFlow;

    private DynamicData taskDelay;

    private DynamicData taskEff;

    private StatData taskDelayDist;

    private StatData taskEffDist;

    private AvgData taskComposition;

    private Queue<Object> xAxisDynamic;

    public TaskStat() {
        taskFlow = new ArrayList<>();
        taskDelay = new DynamicData();
        taskEff = new DynamicData();
        taskDelayDist = new StatData();
        taskEffDist = new StatData();
        taskComposition = new AvgData();
        xAxisDynamic = new LinkedList<>();
    }

    public void init() {
        int[] delayXArr = new int[10];
        int[] effXArr = new int[10];
        for (int i = 0; i < 10; i++) {
            delayXArr[i] = (i + 1) * 100;
            effXArr[i] = (i + 1) * 10;
        }
        taskDelayDist.setXAxis(delayXArr);
        taskEffDist.setXAxis(effXArr);
        Map<String, Queue<Object>> yValueDelay = taskDelay.getYValue();
        Map<String, int[]> yValueDeDist = taskDelayDist.getYValue();
        for (String v : KEY_STORE.TASK_TYPE_ABBR_MAP.values()) {
            yValueDelay.put(String.format("%s-%s", v, KEY_STORE.TO_FLAG_TO), new LinkedList<>());
            yValueDelay.put(String.format("%s-%s", v, KEY_STORE.TO_FLAG_LOCAL), new LinkedList<>());
            yValueDeDist.put(v, new int[10]);
        }
        taskDelay.setYValue(yValueDelay);
        taskDelayDist.setYValue(yValueDeDist);
        taskEff.setYValue(new HashMap<String, Queue<Object>>() {
            {
                put(KEY_STORE.TO_FLAG_TO, new LinkedList<>());
                put(KEY_STORE.TO_FLAG_LOCAL, new LinkedList<>());
            }
        });
        taskEffDist.setYValue(new HashMap<String, int[]>() {
            {
                put(KEY_STORE.TO_FLAG_TO, new int[10]);
                put(KEY_STORE.TO_FLAG_LOCAL, new int[10]);
            }
        });
        taskComposition.setYValue(KEY_STORE.TASK_COMPOSE_LIST.stream().collect(Collectors.toMap(s -> s, s -> 0)));
    }

    public void update(Task task) {
        this.task = task;
        updateTaskFlow();
        updateTaskDynamic();
        updateTaskStat();
    }

    private void updateTaskFlow() {
        // update taskFlow
        taskFlow.clear();
        taskFlow.addAll(Arrays.asList(task.getIndex(), task.getTypeAbbr(), task.getPairs(), task.getEvaluation(), task.getResult()));
    }

    private void updateTaskDynamic() {
        // update x
        StatUtils.pushData(xAxisDynamic, task.getIndex());
        // update y of taskDelay
        Map<String, Queue<Object>> yValueDelay = taskDelay.getYValue();
        StatUtils.pushData(yValueDelay, String.format("%s-%s", task.getTypeAbbr(), KEY_STORE.TO_FLAG_TO), task.getDelay());
        StatUtils.pushData(yValueDelay, String.format("%s-%s", task.getTypeAbbr(), KEY_STORE.TO_FLAG_LOCAL), task.getLocalDelay());
        taskDelay.setYValue(yValueDelay);
        // update y of taskEfficiency
        Map<String, Queue<Object>> yValueEff = taskEff.getYValue();
        StatUtils.pushData(yValueEff, KEY_STORE.TO_FLAG_TO, task.getEfficiency());
        StatUtils.pushData(yValueEff, KEY_STORE.TO_FLAG_LOCAL, task.getLocalEfficiency());
        taskEff.setYValue(yValueEff);
    }

    private void updateTaskStat() {
        // update y of taskEfficiencyDistribution
        Map<String, int[]> yValueEffList = taskEffDist.getYValue();
        StatUtils.collectData(yValueEffList, KEY_STORE.TO_FLAG_TO, (int) (task.getEfficiency() / 10));
        StatUtils.collectData(yValueEffList, KEY_STORE.TO_FLAG_LOCAL, (int) (task.getLocalEfficiency() / 10));
        taskEffDist.setYValue(yValueEffList);
        // update y of taskDelayDistribution
        Map<String, int[]> yValueDeDist = taskDelayDist.getYValue();
        StatUtils.collectData(yValueDeDist, task.getTypeAbbr(), Math.min(9, task.getDelay() / 100));
        taskDelayDist.setYValue(yValueDeDist);
        // update y of taskComposition
        Map<String, Integer> yValueComp = taskComposition.getYValue();
        StatUtils.averageData(yValueComp, task.getDelayComposition(), task.getIndex());
        taskComposition.setYValue(yValueComp);
    }
}